home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / swagg-m / memory.swg / 0032_Another XMS Unit.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-11-02  |  15.9 KB  |  300 lines

  1. {
  2. JD3GTRCW.TRANSCOM@transcom.safb.af.mil (CONROY WILLIAM F)
  3.  
  4. I have seen numerous requests for XMS routines.  Here are some I have
  5. written for a programming effort I headed.
  6. Feel free to use in any way fit.
  7. }
  8.  
  9. {$O+,F+}
  10. UNIT XMSUnit;
  11. {    Programmer:  Major William F. Conroy III                             }
  12. {    Last Mod:    3/12/93                                                 }
  13. {    Touched:     File date set to coorespond to baseline date            }
  14. {                 for Computer Aided Aircrew Scheduling System            }
  15. {                                                                         }
  16. { This unit is written to give access to the XMS memory Specification for }
  17. { the IBM PC.  Do not alter this unit without an excellent understanding  }
  18. { of the PC internal architecture, the Extended Memory Specification(XMS) }
  19. { and the Borland Inline Assembler.  For a much more in depth discussion  }
  20. { of the XMS memory standard and how to implement it on a PC class
  21.   computer }
  22. { Refer to "Extending Dos" by Ray Duncan, Published by Addison Wesley     }
  23.  
  24. INTERFACE
  25.  
  26. TYPE
  27.   PHandlePtrArray = ^THandlePtrArray;
  28.   THandlePtrArray = ARRAY [1..10]OF WORD;
  29.   {  This type definition is used by the graphics system as a way   }
  30.   {  to dynamically allocate space to hold the handles required to  }
  31.   {  access the extended memory.                                    }
  32.  
  33.   PXMSParamBlock  = ^TXMSParamBlock;
  34.   TXMSParamBlock  = RECORD
  35.     LengthOfBlock   : LONGINT;   { Size of block to move }
  36.     SourceEMBHandle : WORD;
  37.     { 0 if source is in conventional memory,       }
  38.     { handle returned by AllocateEMB otherwise     }
  39.     SourceOffset    : LONGINT;
  40.     { if SourceEMBHandle= 0 SourceOffset contains  }
  41.     { a far pointer in Intel standard format else  }
  42.     { SourceOffset indicates offset from the base  }
  43.     { of the block.                                }
  44.     DestEMBHandle   : WORD;
  45.     { 0 if source is in conventional memory,       }
  46.     { handle returned by AllocateEMB otherwise     }
  47.     DestOffset      : LONGINT;
  48.     { if DestEMBHandle= 0 DestOffset contains      }
  49.     { a far pointer in Intel standard format else  }
  50.     { DestOffset indicates offset from the base    }
  51.     { of the block.                                }
  52.   END;
  53.   { This type definition is used by the XMM memory manager for      }
  54.   { block memory moves. As required by the xms specification.       }
  55.  
  56. VAR
  57.   XMSExists : BOOLEAN;
  58.  
  59.   { Function AllocateEMB allocates an Extended Memory Block in Extended }
  60.   { memory.  It requests the block via the Extended Memory Manager(XMM) }
  61.   { It returns True if it was successful False otherwise.  If true, if  }
  62.   { EMB_Handle will contain the Extended Memory Block Handle.  If       }
  63.   {returning false, the errorcode is in the ErrorCode parameter.        }
  64. FUNCTION AllocateEMB(VAR EMB_Handle, ParRequested, ErrorCode : WORD) : BOOLEAN;
  65.  
  66.   { Function FreeEMB releases an Extended Memory Block in Extended Memory }
  67.   { allocated by the AllocateEMB function call.  It requests the XMM      }
  68.   { remove the block.  It returns True if it was successful False         }
  69.   { otherwise.  If true, if block was released correctly.  If returning   }
  70.   { false, the errorcode is in the ErrorCode parameter.                   }
  71. FUNCTION FreeEMB(VAR EMB_Handle, ErrorCode : WORD) : BOOLEAN;
  72.  
  73.   { Function MoveEMB allows memory tranfers between conventional and XMS  }
  74.   { Memory.  This function requires a filled in TXMSParamBlock record.    }
  75.   { It returns True if it was successful False otherwise.  If true, the   }
  76.   { memory block was successfully moved.  If returning false, the         }
  77.   { errorcode is in the ErrorCode parameter.                   }
  78. FUNCTION MoveEMB(PParamBlock : PXMSParamBlock; VAR ErrorCode : WORD) : BOOLEAN;
  79.  
  80.  
  81.  
  82. IMPLEMENTATION
  83.  
  84. VAR
  85.   XMMAddress        : POINTER;
  86.   XMS_Version       : WORD;
  87.   XMM_DriverVersion : WORD;
  88.   HMA_Exists        : BOOLEAN;
  89.   LastErrorCode     : WORD;
  90.  
  91.  
  92. {---------------------------------------------------------------------------}
  93. {                                                                         }
  94. {                             Local Procedure                             }
  95. {                            function XMSPresent                          }
  96. {                                                                         }
  97. {  This function return true if there is an Extended memory manager present }
  98. {  in the system capable of supporting our XMS requests.  It uses a DOS   }
  99. {  multiplexing interrupt request to determine if the driver signiture is }
  100. {  present in the system.  This is the Microsoft recomended method of     }
  101. {  determining the presence of this driver.                               }
  102. {                                                                         }
  103. {---------------------------------------------------------------------------}
  104.  
  105. FUNCTION XMSPresent : BOOLEAN; ASSEMBLER;
  106.  
  107. ASM
  108.   MOV AX, 4300h                  { MultiPlexing interrupt request number  }
  109.   INT 2fh                       { Dos Multiplexing Interrupt             }
  110.   CMP AL, 80h                    { was the signature byte returned in AL  }
  111.   JZ  @1                         { yes?, jump to @1                       }
  112.   MOV AX, 00h                    { set false for return                   }
  113.   JMP @2                        { unconditional jump to end of function  }
  114.  @1:
  115.   MOV AX, 01h                    { set True for return then fall thru to  }
  116.                                 { exit.                                  }
  117.  @2:
  118. END;
  119.  
  120. {------------------------------------------------------------------------- --}
  121. {                                                                          }
  122. {                            Local Procedure                               }
  123. {                      function ReturnDriverAddress                        }
  124. {                                                                          }
  125. {  This function return true if it could determine the device driver entry  }
  126. {  point.  This information is required to call any XMS functions. It uses  }
  127. {  a DOS multiplexing interrupt request to get this address. This is the }
  128. {  Microsoft recomended method of getting the base address of this driver.  }
  129. {  This address is required to setup an indirect call to the driver by the  }
  130. {  XMS functions.                                                           }
  131. {                                                                           }
  132. {---------------------------------------------------------------------------}
  133. FUNCTION ReturnDriverAddress : POINTER; ASSEMBLER;
  134.   {  This function returns the address for the XMM memory manager  }
  135.   {  This value is required to later call the driver for XMS calls }
  136.  
  137. ASM
  138.   MOV AX, 4310h                  { MultiPlexing interrupt request number }
  139.   INT 2fh                       { Dos Multiplexing Interrupt            }
  140.                                 { Set Registers up for Return of Pointer }
  141.   MOV AX, BX                     { Set Offset Value                      }
  142.   MOV DX, ES                     { Set Segment Value                     }
  143. END;
  144.  
  145. {-------------------------------------------------------------------------}
  146. {                                                                         }
  147. {                               Local Procedure                           }
  148. {                            function GetXMSVersion                       }
  149. {                                                                         }
  150. {-------------------------------------------------------------------------}
  151. FUNCTION GetXMSVersion(VAR XMS_Version, XMM_DriverVersion : WORD;
  152.                        VAR HMA_Exists : BOOLEAN;
  153.                        VAR ErrorCode : WORD) : BOOLEAN; ASSEMBLER;
  154.  
  155.   { This function loads the version numbers into the unit global }
  156.   { variables. The information is coded in binary Coded Decimal. }
  157.  
  158. ASM
  159.   XOR  AX, AX                     { set ax to zero                        }
  160.   CALL XMMAddress               { indirect call to XMM driver           }
  161.   CMP  AX, 00h                    { error set ?                           }
  162.   JZ   @1                         { Jump error finish                     }
  163.  
  164.   LES  DI, XMS_Version            { Load XMS_Version Address into es:di   }
  165.   MOV  ES:[DI],AX                { Load variable indirect                }
  166.  
  167.   LES  DI, XMM_DriverVersion      { Load XMM_DriverVrsn Address in es:di  }
  168.   MOV  ES:[DI],BX                { Load variable Indirect                }
  169.  
  170.   LES  DI, HMA_Exists             { Load HMA_Exists Address in es:di      }
  171.   MOV  ES:[DI],DX                { Load variable Indirect                }
  172.  
  173.   LES  DI,ErrorCode              { Load ErrorCode Address into es:di     }
  174.   MOV  WORD PTR ES:[DI],00h      { Clear Error Code                      }
  175.   MOV  AX, 01h                    { set function return to true           }
  176.   JMP  @2                        { Jump to finish                        }
  177.  
  178.  @1:
  179.   LES DI, ErrorCode              { Load error code address in es:di      }
  180.   MOV WORD PTR ES:[DI],00h      { copy 0  into ErrorCode                }
  181.  @2:
  182. END;
  183.  
  184. {-------------------------------------------------------------------------}
  185. {                                                                         }
  186. {                             Exported Procedure                          }
  187. {                            function AllocateEMB                         }
  188. {                                                                         }
  189. {                                                                         }
  190. {    Function AllocateEMB allocates an Extended Memory Block in Extended  }
  191. {    memory.  It requests the block via the Extended Memory Manager(XMM)  }
  192. {    It returns True if it was successful False otherwise.  If true, if   }
  193. {    EMB_Handle will contain the Extended Memory Block Handle.  If        }
  194. {    returning false, the errorcode is in the ErrorCode parameter.        }
  195. {                                                                         }
  196. {-------------------------------------------------------------------------}
  197. FUNCTION AllocateEMB(VAR EMB_Handle, ParRequested,
  198.                          ErrorCode : WORD) : BOOLEAN; ASSEMBLER;
  199.  
  200. ASM
  201.   MOV  AH, 09h                    { set ax for Allocate EMB call       }
  202.   LES  DI, ParRequested           { load ParRequested address in es:di }
  203.   MOV  DX, ES:[DI]                { copy parRequested value in DX      }
  204.   CALL XMMAddress               { indirect call to XMM driver        }
  205.   CMP  AX, 00h                    { error set ?                        }
  206.   JZ   @1                         { Jump error finish                  }
  207.   LES  DI, EMB_Handle             { load EMB_Handle in es:di           }
  208.   MOV  ES:[DI],DX                { copy DX into EMB_Handle            }
  209.   MOV  AX, 01h                    { Return True                        }
  210.   LES  DI, ErrorCode              { Load error code address in es:di   }
  211.   MOV  WORD PTR ES:[DI],00h      { copy 0  into ErrorCode             }
  212.   JMP  @2                        { unconditional jump to finish       }
  213.   { Error Finish                       }
  214.  @1:
  215.   LES  DI, ErrorCode              { load ErrorCode in es:di            }
  216.   MOV  BYTE PTR ES:[DI],BL       { copy BL into ErrorCode             }
  217.  @2:
  218. END;
  219.  
  220. {-------------------------------------------------------------------------}
  221. {                                                                         }
  222. {                           Exported Procedure                            }
  223. {                            function FreeEMB                             }
  224. {                                                                         }
  225. {  Function FreeEMB releases an Extended Memory Block in Extended Memory  }
  226. {  allocated by the AllocateEMB function call.  It requests the XMM       }
  227. {  remove the block.  It returns True if it was successful False          }
  228. {  otherwise.  If true, if block was released correctly.  If returning    }
  229. {  false, the errorcode is in the ErrorCode parameter.                    }
  230. {                                                                         }
  231. {-------------------------------------------------------------------------}
  232. FUNCTION FreeEMB(VAR EMB_Handle, ErrorCode : WORD) : BOOLEAN; ASSEMBLER;
  233.  
  234. ASM
  235.   XOR  AX, AX                     { clear AX to zero                 }
  236.   MOV  AH, 0Ah                    { set ax for Free EMB call         }
  237.   LES  DI, EMB_Handle             { load EMB_Handle address in es:di }
  238.   MOV  DX, ES:[DI]                { load EMB_Handle value in DX      }
  239.   CALL XMMAddress               { indirect call to XMM driver      }
  240.   CMP  AX, 00h                    { error set ?                      }
  241.   JZ   @1                         { Jump error finish                }
  242.   MOV  AX, 01H                    { Set True                         }
  243.   LES  DI, ErrorCode              { Load error code address in es:di }
  244.   MOV  WORD PTR ES:[DI],00h      { copy 0  into ErrorCode           }
  245.   JMP  @2                        { unconditional jump to finish     }
  246.                                 { Error Finish                     }
  247.  @1:
  248.   LES  DI, ErrorCode              { load ErrorCode in es:di          }
  249.   MOV  BYTE PTR ES:[DI],BL       { copy BL into ErrorCode           }
  250.  @2:
  251. END;
  252.  
  253. {-------------------------------------------------------------------------}
  254. {                                                                         }
  255. {                           Exported Procedure                            }
  256. {                            function MoveEMB                             }
  257. {                                                                         }
  258. {  Function MoveEMB allows memory tranfers between conventional and XMS   }
  259. {  Memory.  This function requires a filled in TXMSParamBlock record.     }
  260. {  It returns True if it was successful False otherwise.  If true, the    }
  261. {  memory block was successfully moved.  If returning false, the          }
  262. {  errorcode is in the ErrorCode parameter.                               }
  263. {                                                                         }
  264. {-------------------------------------------------------------------------}
  265. FUNCTION MoveEMB(PParamBlock : PXMSParamBlock;
  266.                  VAR ErrorCode : WORD) : BOOLEAN; ASSEMBLER;
  267.  
  268. ASM
  269.   MOV  AX, DS                     { move DS to AX register                }
  270.   MOV  ES, AX                     { move AX to ES register                }
  271.   MOV  AH, 0Bh                    { set ax for Move EMB call              }
  272.   PUSH DS                       { push DS to Stack                      }
  273.   LDS  SI, PParamBlock            { load PParamBlock Address to ds:si     }
  274.   MOV  DI, OFFSET XMMAddress      { move XMMAddress offset to di          }
  275.   CALL DWORD PTR ES:[DI]        { indirect call to XMMdriver via es:di  }
  276.   POP  DS                        { save TP's data segment                }
  277.   CMP  AX, 00h                    { error set ?                           }
  278.   JZ   @1                         { Jump error finish                     }
  279.   MOV  AX, 01H                    { Set True                              }
  280.   LES  DI, ErrorCode              { Load error code address in es:di      }
  281.   MOV  WORD PTR ES:[DI],00h      { copy 0  into ErrorCode                }
  282.   JMP  @2                        { unconditional jump to finish          }
  283.                                 { Error Finish                          }
  284.  @1:
  285.   LES  DI, ErrorCode              { load ErrorCode in es:di               }
  286.   MOV  WORD PTR ES:[DI],AX       { Clear ErrorCode prior to load         }
  287.   MOV  BYTE PTR ES:[DI],BL       { copy BL into ErrorCode                }
  288.   MOV  AX, 01h                    { Return False                          }
  289.  @2:
  290. END;
  291.  
  292. BEGIN
  293.   XMSExists := XMSPresent;
  294.   IF XMSExists THEN
  295.   BEGIN
  296.     XMMAddress := ReturnDriverAddress;
  297.     GetXMSVersion(XMS_Version, XMM_DriverVersion, HMA_Exists, LastErrorCode);
  298.   END;
  299. END.
  300.